﻿<!DOCTYPE html>
<html>
<head>
<!----------------------------------------------------------
 
	Copyright (c) 2015-2018 Jean-Marc VIGLINO, 
	released under CeCILL-B (french BSD like) licence: http://www.cecill.info/
	
------------------------------------------------------------>
	<title>ol-ext: stroke pattern</title>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	
	<meta name="description" content="an OL3 stroke style with a set of cartographic patterns to use in your maps." />
	<meta name="keywords" content="ol3, vector, style, stroke, fill, pattern, hatch, hatching" />

	<link rel="stylesheet" href="../style.css" />

	<!-- jQuery -->
	<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
	<!-- FontAwesome -->
	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

	<!-- Openlayers -->
    <link rel="stylesheet" href="https://openlayers.org/en/latest/css/ol.css" />
	<script type="text/javascript" src="https://openlayers.org/en/latest/build/ol.js"></script>
	<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL,Object.assign"></script>
	
	<!-- ol-ext -->
	<script type="text/javascript" src="../../dist/ol-ext.js"></script>

	<style>
		#select
		{	box-shadow:1px 1px 3px #000;
			background:#fff;
			margin-left:0.5em;
			display:inline-block;
			width:50px;
			height:40px;
		}
		label
		{	width:7em;
			text-align:right;
			display: inline-block;
		}
		input[type=number]
		{	width:4em;
		}
		#pselect
		{	max-width:300px;
			position: absolute;
			box-shadow:1px 1px 3px #000;
			background:#fff;
		}
		#pselect > div
		{	float: left;
			width: 50px;
			height: 40px;
			background-color: #fff;
			border:2px solid #000;
			box-sizing: border-box;
		}
		#pselect > div:hover
		{	border-color: red;
		}
	</style>

</head>
<body >
	<a href="https://github.com/Viglino/ol-ext" class="icss-github-corner"><i></i></a>

	<a href="../../index.html">
		<h1>ol-ext: stroke pattern</h1>
	</a>
	<div class="info">
		<p>
			<i>ol.style.StrokePattern</i> set stroke pattern style to vector features.
			It uses the cartographic patterns of the <a href="map.style.pattern.html">ol.style.FillPattern</a>.
		</p>
		<p>
			Hatching can be defined with a <i>size </i> for the lines, <i>spacing</i> interval and an <i>angle</i>.
			<br />
			Cross, square, tile, dot and circle patterns can be defines with a <i>size</i> and <i>spacing</i> interval. 
			The <i>angle</i> option is a boolean (0|1) for 45&deg; pattern.
		</p><p>
			You can use font to create a pattern (like FontAwesome patterns in the example <i class="fa fa-smile-o"></i>). NB the font must be loaded before pattern creation.
		</p>
	</div>

	<!-- Map div -->
	<div id="map" style="width:600px; height:400px;"></div>

	<div class="options" style="min-width:300px;">
		<h2>Options:</h2>
		<ul>
			<li>
				Pattern: <div id="select"></div>
				<div id="pselect"></div>
			</li>
			<li style="clear:both;">
				<label>Size:</label>
				<input id="size" type="number" min=0 value=5 onchange="refresh()" />
			</li>
			<li>
				<label>Spacing: </label>
				<input id="spacing" type="number" min=0 value=10 onchange="refresh()" /> 
			</li>
			<li>
				<label>Angle: </label>
				<input id="angle" type="number" value=0 onchange="refresh()" /> <small>(deg)</small>
			</li>
			<li>
				<label>Offset: </label>
				<input id="offset" type="number" value=0 onchange="refresh()" />
			</li>
			<li>
				<label>Scale: </label>
				<input id="scale" type="number" value=1 onchange="refresh()" min=0 step=0.5 />
			</li>
			<li>
				<label>Color: </label>
				<select id="color" onchange="refresh()">
					<option value="blue">blue</option>
					<option value="red">red</option>
					<option value="green">green</option>
					<option value="yellow">yellow</option>
				</select>
			</li>
			<li>
				<label>Background: </label>
				<select id="bg" onchange="refresh()">
					<option value="rgba(0,255,0,0.5)">green</option>
					<option value="rgba(255,255,255,0.3)">white</option>
					<option value="rgba(0,0,0,0)">transparent</option>
					<option value="rgba(0,0,255,0.3)">blue</option>
					<option value="rgba(255,0,0,0.3)">red</option>
					<option value="rgba(255,255,0,0.5)">yellow</option>
				</select>
			</li>
		</ul>
		<!-- force font loading -->
		<i class="fa fa-bug" style="visibility:hidden"></i>
	</div>
	

	<script type="text/javascript">

	var refreh;
	var imgFile = '../data/pattern.png';
	
	$(window).load (function()
	{	// AddChar patterns
		ol.style.FillPattern.addPattern ("copy (char pattern)", { char:"©" });
		ol.style.FillPattern.addPattern ("bug (fontawesome)", { char:'\uf188', size:12, font:"10px FontAwesome" });
		ol.style.FillPattern.addPattern ("smiley (width angle)", { char:'\uf118', size:20, angle:true, font:"15px FontAwesome" });

		// Popup
		$("#select").click(function(){
			$("#pselect").toggle();
		});

		var pat = "hatch"
		var spattern = $("#pselect");
		for (var i in ol.style.FillPattern.prototype.patterns) {
			var p = new ol.style.FillPattern({ pattern:i })
			$("<div>").attr('title',i)
				.css("background-image",'url("'+p.getImage().toDataURL()+'")')
				.click(function(){ pat = $(this).attr("title"); refresh(); })
				.appendTo(spattern);
		}
		var p = new ol.style.FillPattern({ image: new ol.style.Icon({ src : imgFile }) });
		$("<div>").attr('title','Image (PNG)')
				.css("background-image",'url("'+imgFile+'")')
				.click(function(){ pat = $(this).attr("title"); refresh(); })
				.appendTo(spattern);

		// Redraw map
		refresh = function() {
			$("#pselect").hide();
			vector.changed();
			if ( $.inArray(pat,["hatch","cross","dot","circle","square","tile"]) < 0 ){
				$("#size").prop("disabled",true);
				$("#spacing").prop("disabled",true);
				$("#angle").prop("disabled",true);
				$("#angle").next().text("");
			} else {
				$("#size").prop("disabled",false);
				$("#spacing").prop("disabled",false);
				$("#angle").prop("disabled",false);
				if (pat=="hatch") $("#angle").next().text("(deg)");
				else $("#angle").next().text("(bool)");
			}
			// Calculate image to be drawn outside the map
			var p = new ol.style.FillPattern({
				pattern: pat,
				image: (pat=='Image (PNG)') ? new ol.style.Icon({ src : imgFile }) : undefined,
				ratio: 2,
				color: "#000",
				size: Number($("#size").val()),
				spacing: Number($("#spacing").val()),
				angle: Number($("#angle").val())
			});
			$("#select").css('background-image', 'url('+p.getImage().toDataURL()+')');
		};

		// Layers
		var layer = new ol.layer.Tile({
			title:'terrain-background',
			source: new ol.source.Stamen({ layer: 'terrain' })
		});

		// The map
		var map = new ol.Map({
			target: 'map',
			view: new ol.View
			({	zoom: 5,
				center: [166326, 5992663]
			}),
			layers: [layer]
		});

		function getStyle(feature){
			var p = pat;
			return [ new ol.style.Style({
				stroke: new ol.style.StrokePattern({	
					width: 8,
					pattern: (p!='Image (PNG)') ? p : undefined,
					image: (p=='Image (PNG)') ? new ol.style.Icon({ src : imgFile }) : undefined,
					color: $("#color").val(),
					offset: Number($("#offset").val()),
					scale: Number($("#scale").val()),
					fill: new ol.style.Fill ({ color:$("#bg").val() }),
					size: Number($("#size").val()),
					spacing: Number($("#spacing").val()),
					angle: Number($("#angle").val())
				})
			})];
		}

		// Nouvelle source de donnee
		var vector = new ol.layer.Vector({
			source: new ol.source.Vector(),
			style: getStyle
		})
		map.addLayer(vector);
		vector.getSource().addFeature(new ol.Feature(new ol.geom.Polygon([[[259274, 6398696], [63595, 5958419], [635956, 5772524], [259274, 6398696]]])));

		// global so we can remove it later
		var interaction = new ol.interaction.Draw({
			type: 'Polygon',
			source: vector.getSource()
		});
		map.addInteraction(interaction); 

		refresh();
	});
	</script>

</body>
</html>